package net.pulseproject.router.modules.logic.beatstabilizer;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class BeatHistory {

	public static final long NOT_ENOUGH_DATA = -42;
	
	private static final Log LOG = LogFactory.getLog(BeatHistory.class);
	
	private final List<Long> timestamps = new LinkedList<Long>();
	
	private final long timeToLiveInMs;
	
	
	public BeatHistory(long timeToLiveInMs) {
		this.timeToLiveInMs = timeToLiveInMs;
	}

	public synchronized void add() {
		LOG.trace("add()");
		this.timestamps.add(Long.valueOf(System.currentTimeMillis()));
	}

	public synchronized long calcAverageDuration() {
		this.removeOldTimestamps();

		if(this.timestamps.size() < 2) {
			LOG.trace("calcAverageDuration() ... not enough up2date history data available");
			return NOT_ENOUGH_DATA;
		}
		
		long result = -1;
		for (int i = 1; i < this.timestamps.size(); i++) {
			long stamp1 = this.timestamps.get(i - 1).longValue();
			long stamp2 = this.timestamps.get(i).longValue();
			long diff = stamp2 - stamp1;
			if(result == -1) {
				result = diff;
			} else {
				result = (result + diff) / 2;
			}
		}
		
		LOG.trace("calcAverageDuration() ... returning average of "+result+" for "+this.timestamps.size()+" timestamps");
		return result;
	}
	
	private void removeOldTimestamps() {
		Set<Long> tooOld = new HashSet<Long>();
		long time = System.currentTimeMillis();
		for (Long beat : this.timestamps) {
			long diff = time - beat.longValue();
			if(diff > this.timeToLiveInMs) {
				tooOld.add(beat);
			}
		}
		LOG.trace("removeOldBeats() ... removing " + tooOld.size() + " beat(s)");
		this.timestamps.removeAll(tooOld);
	}
	
}
